package com.ctgu.tengyun.controller.product;

import com.ctgu.tengyun.bean.convert.ProductGuideConvert;
import com.ctgu.tengyun.bean.errorcode.CommonErrorCode;
import com.ctgu.tengyun.bean.errorcode.ProductGuideErrorCode;
import com.ctgu.tengyun.bean.request.SaveProductGuideRequest;
import com.ctgu.tengyun.bean.response.ProductGuideListResponse;
import com.ctgu.tengyun.bean.response.ProductHistoryResponse;
import com.ctgu.tengyun.bean.response.ProductLogListResponse;
import com.ctgu.tengyun.domain.ProductGuideInfo;
import com.ctgu.tengyun.domain.ProductGuideLog;
import com.ctgu.tengyun.domain.ProductInfo;
import com.ctgu.tengyun.domain.SysUser;
import com.ctgu.tengyun.exception.ErrorCodeException;
import com.ctgu.tengyun.service.product.ProductGuideInfoService;
import com.ctgu.tengyun.service.product.ProductGuideLogService;
import com.ctgu.tengyun.service.product.ProductInfoService;
import com.ctgu.tengyun.service.user.SysUserService;
import com.ctgu.tengyun.util.*;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by liaoweizhi on 2019/7/23.
 */
@RestController
@RequestMapping(value = "/v1/product_guide/")
public class ProductGuideController {

    @Resource
    private ProductInfoService productInfoService;
    @Resource
    private ProductGuideInfoService productGuideInfoService;
    @Resource
    private ProductGuideLogService productGuideLogService;
    @Resource
    private SysUserService sysUserService;

    @GetMapping(value = "list_all")
    public ProductGuideListResponse listInfo(HttpServletRequest request) {
        String productNo = ParameterTool.getParameterString(request, "productNo", "");
        Integer pid = null;
        ProductInfo productInfo = null;

        if (StringUtils.isNotEmpty(productNo)) {
            productInfo = productInfoService.selectByProductNo(productNo);
            if (null == productInfo) {
                return new ProductGuideListResponse(Collections.emptyList());
            }
            pid = productInfo.getId();
        }

        List<ProductGuideInfo> guideInfoList = productGuideInfoService.selectGuideList(pid);
        Set<Integer> pidSet = CollectionsUtil.getComposerIdSet(guideInfoList, ProductGuideInfo.PID_MAP_COMPOSER);
        List<ProductInfo> productInfoList = productInfoService.selectByIds(pidSet);
        Map<Integer, ProductInfo> idProductInfoMap = CollectionsUtil.mapComposerId(productInfoList, ProductInfo.ID_COMPOSER);

        return ProductGuideConvert.toProductGuideListResponse(guideInfoList, idProductInfoMap);
    }

    @RequestMapping(value = "detail/{id}", method = RequestMethod.GET)
    public ProductLogListResponse detail(@PathVariable("id") Integer id) {
        List<ProductGuideLog> guideLogList = productGuideLogService.selectByGid(Lists.newArrayList(id));
        Set<Long> operationUserIdSet = CollectionsUtil.getComposerIdSet(guideLogList, ProductGuideLog.OPERATION_USER_ID_COMPOSER);
        List<SysUser> sysUserList = sysUserService.selectByIds(operationUserIdSet);
        Map<Long, SysUser> idSysUserMap = CollectionsUtil.mapComposerId(sysUserList, SysUser.ID_COMPOSER);

        return ProductGuideConvert.toProductLogListResponse(guideLogList, idSysUserMap);
    }

    @RequestMapping(value = "history/{productNo}", method = RequestMethod.GET)
    public ProductHistoryResponse history(@PathVariable("productNo") String productNo) {
        ProductInfo productInfo = productInfoService.selectByProductNo(productNo);
        Validator.assertResourceFound(null != productInfo, "product not found, productNo:" + productNo);

        List<ProductGuideInfo> guideInfoList = productGuideInfoService.selectGuideList(productInfo.getId());
        Set<Integer> idSet = CollectionsUtil.getComposerIdSet(guideInfoList, ProductGuideInfo.ID_MAP_COMPOSER);
        List<ProductGuideLog> guideLogList = Lists.newArrayList();
        idSet.forEach(item -> {
            guideLogList.addAll(productGuideLogService.selectByGid(Lists.newArrayList(item)));
        });

        Set<Long> operationUserIdSet = CollectionsUtil.getComposerIdSet(guideLogList, ProductGuideLog.OPERATION_USER_ID_COMPOSER);
        List<SysUser> sysUserList = sysUserService.selectByIds(operationUserIdSet);
        Map<Long, SysUser> idSysUserMap = CollectionsUtil.mapComposerId(sysUserList, SysUser.ID_COMPOSER);

        return ProductGuideConvert.toProductHistoryResponse(productInfo, guideLogList, idSysUserMap);
    }

    @RequestMapping(value = "save_or_update", method = RequestMethod.POST)
    public Object save(HttpServletRequest httpServletRequest, @RequestBody SaveProductGuideRequest request) {
        Long userId = RequestExtract.getUserId(httpServletRequest);
        ProductGuideInfo guideInfo = ProductGuideConvert.fromSaveProductGuideRequest(request);
        String productNo = request.getProductNo();
        ProductInfo productInfo = productInfoService.selectByProductNo(productNo);
        if (null == productInfo) {
            throw new ErrorCodeException(ProductGuideErrorCode.invalid_product_no, ProductGuideErrorCode.invalid_product_no.getMsg());
        }

        if (null != request.getId()) {
            ProductGuideInfo oldGuideInfo = productGuideInfoService.selectByPrimaryKey(request.getId());
            Validator.assertResourceFound(null != oldGuideInfo, "product guide not found, guide id:" + request.getId());
            guideInfo.setVersion(oldGuideInfo.getVersion());

            if (productGuideInfoService.updateByPrimaryKeySelective(guideInfo) &&
                    !guideInfo.getGuideFile().getUrl().equals(oldGuideInfo.getGuideFile().getUrl())) {
                productGuideLogService.insertSelective(toProductGuideLog(guideInfo, userId));
            }
        } else {
            guideInfo.setPid(productInfo.getId());
            try {
                productGuideInfoService.insertSelective(guideInfo);
            } catch (DuplicateKeyException e) {
                throw new ErrorCodeException(CommonErrorCode.duplicate_add, CommonErrorCode.duplicate_add.getMsg());
            }
            productGuideLogService.insertSelective(toProductGuideLog(guideInfo, userId));
        }

        return ImmutableMap.of("id", guideInfo.getId());
    }

    private ProductGuideLog toProductGuideLog(ProductGuideInfo guideInfo, Long userId) {
        ProductGuideLog guideLog = new ProductGuideLog();
        guideLog.setGid(guideInfo.getId());
        guideLog.setGuideType(guideInfo.getGuideType());
        guideLog.setGuideFile(guideInfo.getGuideFile());
        guideLog.setRemark(guideInfo.getRemark());
        guideLog.setOperationUserId(userId);

        return guideLog;
    }

}
